﻿#include "HUD.h" 

HUD::HUD(void)
{
}

HUD::~HUD(void)
{
}

osg::Drawable* HUD::BoundingBox(osg::Geode* geode)
{
	osg::BoundingBox bb;
	for(unsigned int i=0;i<geode->getNumDrawables();++i)
	{
		bb.expandBy(geode->getDrawable(i)->getBound());
	}

	osg::Geometry* geom = new osg::Geometry;

	osg::Vec3Array* vertices = new osg::Vec3Array;
	float depth = bb.zMin()-0.1;
	vertices->push_back(osg::Vec3(bb.xMin(),bb.yMax(),depth));
	vertices->push_back(osg::Vec3(bb.xMin(),bb.yMin(),depth));
	vertices->push_back(osg::Vec3(bb.xMax(),bb.yMin(),depth));
	vertices->push_back(osg::Vec3(bb.xMax(),bb.yMax(),depth));
	geom->setVertexArray(vertices);

	osg::Vec3Array* normals = new osg::Vec3Array;
	normals->push_back(osg::Vec3(0.0f,0.0f,1.0f));
	geom->setNormalArray(normals, osg::Array::BIND_OVERALL);

	osg::Vec4Array* colors = new osg::Vec4Array;
	colors->push_back(osg::Vec4(1.0f,1.0,0.8f,0.2f));
	geom->setColorArray(colors, osg::Array::BIND_OVERALL);

	geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,4));

	osg::StateSet* stateset = geom->getOrCreateStateSet();
	stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
	//stateset->setAttribute(new osg::PolygonOffset(1.0f,1.0f),osg::StateAttribute::ON);
	stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);

	return geom;
}

osg::Camera* HUD::create(int x, int y, int width, int height)
{
	osg::Camera* camera = new osg::Camera;

	camera->setViewMatrix(osg::Matrix::identity());
	camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
	
	//camera->setProjectionMatrix(osg::Matrix::ortho2D(x, x+width, y, y+height));
	camera->setProjectionMatrixAsOrtho2D(x, x+width, y, y+height);
	// only clear the depth buffer
	camera->setClearMask(GL_DEPTH_BUFFER_BIT);
	// draw subgraph after main camera view.
	camera->setRenderOrder(osg::Camera::POST_RENDER);

	camera->setViewport(x, y, x+width, y+height);
	// we don't want the camera to grab event focus from the viewers main camera(s).
	camera->setAllowEventFocus(false);

	return camera;
}

void HUD::setHUDStateSet(osg::Node &node)
{
	osg::StateSet* state = node.getOrCreateStateSet();

	// turn lighting off for the text and disable depth test to ensure it's always ontop.
	state->setMode(GL_LIGHTING, osg::StateAttribute::OFF);		// 关闭光照
	state->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);	// 关闭深度测试

	state->setMode(GL_BLEND, osg::StateAttribute::ON);			// 纹理?
	state->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);	// ?
}


osg::StateSet* HUD::createHUDStateSet()
{
	// 我们需要创建一个osg::StateSet，并禁止深度测试（总是在屏幕上绘制），允许Alpha 混合
	// （使HUD 背景透明），以保证HUD 的渲染正确。然后我们使用一个指定数字的渲染元来分配
	// 几何体在拣选遍历中的渲染顺序。代码如下所示：
	// 设置渲染状态，使用上面定义的纹理
	osg::StateSet* HUDStateSet = new osg::StateSet();
	/*
	osg::Texture2D* HUDTexture = new osg::Texture2D;
	HUDTexture->setDataVariance(osg::Object::DYNAMIC);
	osg::Image* hudImage;
	hudImage = osgDB::readImageFile("Images/land_shallow_topo_2048.jpg");
	//hudImage = osgDB::readImageFile("hudbk.jpg");
	HUDTexture->setImage(hudImage);
	HUDStateSet->setTextureAttributeAndModes(0,HUDTexture,osg::StateAttribute::ON);
	*/
	//打开GL_BLEND 混合模式（以保证Alpha 纹理正确）
	HUDStateSet->setMode(GL_BLEND, osg::StateAttribute::ON);

	HUDStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
	// 禁止深度测试，因此几何体将忽略已绘制物体的深度值，直接进行绘制
	HUDStateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
	HUDStateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
	// 确认该几何题在最后进行绘制。渲染元（RenderBin）按照数字顺序执行渲染，因此我们设置一个较大的数字值
	//HUDStateSet->setRenderBinDetails(11, "RenderBin");
	return HUDStateSet;
}


osg::Geometry* HUD::createHUDBGRect()
{
	// 设置HUD 的四边形背景，并添加到Geode 节点
	osg::Geometry* HUDBackgroundGeometry = new osg::Geometry();
	osg::Vec3Array* HUDBackgroundVertices = new osg::Vec3Array;
	HUDBackgroundVertices->push_back(osg::Vec3(0,    568, -1));
	HUDBackgroundVertices->push_back(osg::Vec3(1024, 568, -1));
	HUDBackgroundVertices->push_back(osg::Vec3(1024, 768, -1));
	HUDBackgroundVertices->push_back(osg::Vec3(0,    768, -1));
	osg::DrawElementsUInt* HUDBackgroundIndices = new osg::DrawElementsUInt(osg::PrimitiveSet::POLYGON, 0);
	HUDBackgroundIndices->push_back(0);
	HUDBackgroundIndices->push_back(1);
	HUDBackgroundIndices->push_back(2);
	HUDBackgroundIndices->push_back(3);
	osg::Vec4Array* HUDcolors = new osg::Vec4Array;
	HUDcolors->push_back(osg::Vec4(0.1f, 0.2f, 0.4f, 0.80f));
	osg::Vec2Array* texcoords = new osg::Vec2Array(4);
	(*texcoords)[0].set(0.0f, 0.0f);
	(*texcoords)[1].set(1.0f, 0.0f);
	(*texcoords)[2].set(1.0f, 1.0f);
	(*texcoords)[3].set(0.0f, 1.0f);
	HUDBackgroundGeometry->setTexCoordArray(0, texcoords);

	osg::Vec3Array* HUDnormals = new osg::Vec3Array;
	HUDnormals->push_back(osg::Vec3(0.0f, 0.0f, 1.0f));
	HUDBackgroundGeometry->setNormalArray(HUDnormals);
	HUDBackgroundGeometry->setNormalBinding(osg::Geometry::BIND_OVERALL);
	HUDBackgroundGeometry->addPrimitiveSet(HUDBackgroundIndices);
	HUDBackgroundGeometry->setVertexArray(HUDBackgroundVertices);
	HUDBackgroundGeometry->setColorArray(HUDcolors);
	HUDBackgroundGeometry->setColorBinding(osg::Geometry::BIND_OVERALL);
	return HUDBackgroundGeometry;
}